package com.gzh.teaching.service.impl;

import com.gzh.core.chche.service.CacheManage;
import com.gzh.core.chche.service.dto.School;
import com.gzh.core.dao.mapper.*;
import com.gzh.core.dao.po.*;
import com.gzh.core.util.CosUtils;
import com.gzh.core.util.NumericHelper;
import com.gzh.core.util.StringUtils;
import com.gzh.core.util.constant.ErrorCode;
import com.gzh.core.util.exception.BusinessException;
import com.gzh.teaching.client.ServiceClient;
import com.gzh.teaching.dao.mapper.TeacherMapper;
import com.gzh.teaching.dao.po.CourseUserBean;
import com.gzh.teaching.model.vo.*;
import com.gzh.teaching.service.TeacherService;
import com.gzh.teaching.service.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TeacherServiceImpl implements TeacherService {

    @Autowired
    private FileMapper fileMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkMapper workMapper;
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private ChooseMapper chooseMapper;
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private CacheManage cacheManage;
    @Autowired
    private CompleteMapper completeMapper;
    @Autowired
    private AcademyMapper academyMapper;
    @Autowired
    private ClassMapper classMapper;
    @Autowired
    private CheckMapper checkMapper;
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ServiceClient serviceClient;

    @Override
    @Transactional
    public void addCourse(AddCourseIn in) {
        Integer fileId = in.getFileId();
        FileEntity fileEntityQuery = new FileEntity();
        fileEntityQuery.setFileId(fileId);
        FileEntity fileEntity = fileMapper.selectOne(fileEntityQuery);
        String imgUrl = CosUtils.getImg(fileEntity.getBucketName(), fileEntity.getPath());
        CourseEntity courseEntity = new CourseEntity();
        courseEntity.setCourseName(in.getCourseName());
        courseEntity.setTeacherId(in.getUserId());
        courseEntity.setCourseType(in.getCourseType());
        courseEntity.setCredit(in.getCredit());
        courseEntity.setStatus(0);
        courseEntity.setImgPath(imgUrl);
        courseEntity.setCreateDate(NumericHelper.toInteger(StringUtils.formatDate()));
        courseEntity.setCreateTime(NumericHelper.toInteger(StringUtils.formatTime()));
        courseMapper.insertSelective(courseEntity);
    }

    @Override
    public List<CourseQueryOut> getCourseList(CourseQueryIn in) {
        List<CourseQueryOut> list = new ArrayList<>();
        Integer userId = in.getUserId();
        Condition courseCondition = new Condition(CourseEntity.class);
        Example.Criteria criteria = courseCondition.createCriteria();
        criteria.andIn("status", Arrays.asList(0, 2));
        criteria.andEqualTo("teacherId", userId);
        if (in.getKey() != null) {
            criteria.andEqualTo("courseId", in.getKey());
        }
        courseCondition.setOrderByClause("create_date desc,create_time desc");
        List<CourseEntity> courseEntities = courseMapper.selectByCondition(courseCondition);
        //查询用户
        UserEntity userEntityQuery = new UserEntity();
        userEntityQuery.setUserId(userId);
        UserEntity userEntity = userMapper.selectOne(userEntityQuery);
        for (CourseEntity courseEntity : courseEntities) {
            CourseQueryOut out = new CourseQueryOut();
            out.setCourseId(StringUtils.toString(courseEntity.getCourseId()));
            out.setCourseName(courseEntity.getCourseName());
            out.setImgPath(courseEntity.getImgPath());
            out.setUserName(userEntity.getFullName());
            out.setCourseType(StringUtils.toString(courseEntity.getCourseType()));
            out.setStatus(StringUtils.toString(courseEntity.getStatus()));
            out.setCreateDate(StringUtils.toString(courseEntity.getCreateDate()));
            out.setCreateTime(StringUtils.toString(courseEntity.getCreateTime()));
            out.setCredit(StringUtils.toString(courseEntity.getCredit()));
            out.setIntroduce(courseEntity.getIntroduce());
            out.setScaleOne(StringUtils.toString(courseEntity.getScaleOne()));
            out.setScaleTwo(StringUtils.toString(courseEntity.getScaleTwo()));
            out.setScaleThree(StringUtils.toString(courseEntity.getScaleThree()));
            list.add(out);
        }
        return list;
    }

    @Override
    @Transactional
    public SaveJobOut saveJob(SaveJobIn in) {
        SaveJobOut out = new SaveJobOut();
        Integer workId = in.getWorkId();
        WorkEntity workEntity = new WorkEntity();
        workEntity.setWorkName(in.getTitle());
        if (workId == null) {
            workEntity.setCourseId(in.getCourseId());
            workEntity.setWorkType(in.getWorkType());
            workEntity.setCreateDate(NumericHelper.toInteger(StringUtils.formatDate()));
            workEntity.setCreateTime(NumericHelper.toInteger(StringUtils.formatTime()));
            workMapper.insertSelective(workEntity);
            workId = workEntity.getWorkId();
        } else {
            Condition workCondition = new Condition(WorkEntity.class);
            workCondition.createCriteria().andEqualTo("workId", workId);
            workMapper.updateByConditionSelective(workEntity, workCondition);
            Condition questionCondition = new Condition(QuestionEntity.class);
            questionCondition.createCriteria().andEqualTo("workId", workId);
            questionMapper.deleteByCondition(questionCondition);
        }
        final Integer finalWorkId = workId;
        List<SingleVo> singleList = in.getSingleList();
        if (!CollectionUtils.isEmpty(singleList)){
            List<QuestionEntity> singleQuestion = singleList.stream().map(t -> t.toEntity(finalWorkId)).collect(Collectors.toList());
            questionMapper.insertList(singleQuestion);
        }
        List<MultipleVo> multipleList = in.getMultipleList();
        if (!CollectionUtils.isEmpty(multipleList)){
            List<QuestionEntity> multipleQuestion = multipleList.stream().map(t -> t.toEntity(finalWorkId)).collect(Collectors.toList());
            questionMapper.insertList(multipleQuestion);
        }
        List<FillVo> fillList = in.getFillList();
        if (!CollectionUtils.isEmpty(fillList)){
            List<QuestionEntity> fillQuestion = fillList.stream().map(t -> t.toEntity(finalWorkId)).collect(Collectors.toList());
            questionMapper.insertList(fillQuestion);
        }
        List<JudgeVo> judgeList = in.getJudgeList();
        if (!CollectionUtils.isEmpty(judgeList)){
            List<QuestionEntity> judgeQuestion = judgeList.stream().map(t -> t.toEntity(finalWorkId)).collect(Collectors.toList());
            questionMapper.insertList(judgeQuestion);
        }
        List<ShortVo> shortList = in.getShortList();
        if (!CollectionUtils.isEmpty(shortList)){
            List<QuestionEntity> shortQuestion = shortList.stream().map(t -> t.toEntity(finalWorkId)).collect(Collectors.toList());
            questionMapper.insertList(shortQuestion);
        }
        return out;
    }

    @Override
    public List<GetJobOut> getJob(GetJobIn in) {
        List<GetJobOut> list = new ArrayList<>();
        Integer courseId = in.getCourseId();
        Condition workCondition = new Condition(WorkEntity.class);
        workCondition.createCriteria().andEqualTo("courseId", courseId);
        workCondition.setOrderByClause("create_date desc,create_time desc");
        List<WorkEntity> workEntityList = workMapper.selectByCondition(workCondition);
        List<Integer> fileIdList = workEntityList.stream().filter(t -> t.getWorkType().equals(1)).map(t -> t.getFileId()).collect(Collectors.toList());
        List<FileEntity> fileEntityList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fileIdList)) {
            Condition fileCondition = new Condition(FileEntity.class);
            fileCondition.createCriteria().andIn("fileId", fileIdList);
            fileEntityList = fileMapper.selectByCondition(fileCondition);
        }
        for (WorkEntity workEntity : workEntityList) {
            GetJobOut getJobOut = new GetJobOut(workEntity);
            if (workEntity.getWorkType().equals(1)) {
                List<FileEntity> entities = fileEntityList.stream().filter(t -> t.getFileId().equals(workEntity.getFileId())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(entities)) {
                    String objectUrl = CosUtils.getImg(entities.get(0).getBucketName(), entities.get(0).getPath());
                    getJobOut.setFilePath(objectUrl);
                    getJobOut.setFileName(entities.get(0).getFileName());
                }
            }
            list.add(getJobOut);
        }
        return list;
    }

    @Override
    public GetQuestionOut getQuestion(GetJobIn in) {
        GetQuestionOut out = new GetQuestionOut();
        List<SingleVo> singleList = new ArrayList<>();
        List<MultipleVo> multipleList = new ArrayList<>();
        List<FillVo> fillList = new ArrayList<>();
        List<JudgeVo> judgeList = new ArrayList<>();
        List<ShortVo> shortList = new ArrayList<>();
        if (in.getWorkId() == null) {
            out.setSingleList(singleList);
            out.setMultipleList(multipleList);
            out.setFillList(fillList);
            out.setJudgeList(judgeList);
            out.setShortList(shortList);
            return out;
        }
        //
        WorkEntity workEntityQuery = new WorkEntity();
        workEntityQuery.setWorkId(in.getWorkId());
        WorkEntity workEntity = workMapper.selectOne(workEntityQuery);
        out.setTitle(workEntity.getWorkName());
        //
        Condition questionCondition = new Condition(QuestionEntity.class);
        questionCondition.createCriteria().andEqualTo("workId", in.getWorkId());
        List<QuestionEntity> questionEntityList = questionMapper.selectByCondition(questionCondition);
        Map<Integer, List<QuestionEntity>> listMap = questionEntityList.stream().collect(Collectors.groupingBy(t -> t.getQuestionType()));
        for (Map.Entry<Integer, List<QuestionEntity>> entry : listMap.entrySet()) {
            Integer key = entry.getKey();
            List<QuestionEntity> value = entry.getValue();
            if (key == 1) {
                singleList = value.stream().map(t -> new SingleVo(t)).collect(Collectors.toList());
            }
            if (key == 2) {
                multipleList = value.stream().map(t -> new MultipleVo(t)).collect(Collectors.toList());
            }
            if (key == 3) {
                fillList = value.stream().map(t -> new FillVo(t)).collect(Collectors.toList());
            }
            if (key == 4) {
                judgeList = value.stream().map(t -> new JudgeVo(t)).collect(Collectors.toList());
            }
            if (key == 5) {
                shortList = value.stream().map(t -> new ShortVo(t)).collect(Collectors.toList());
            }
        }
        out.setSingleList(singleList);
        out.setMultipleList(multipleList);
        out.setFillList(fillList);
        out.setJudgeList(judgeList);
        out.setShortList(shortList);
        return out;
    }

    @Override
    @Transactional
    public PublishWorkOut publishWork(PublishWorkIn in) {
        Integer date = NumericHelper.toInteger(StringUtils.formatDate());
        Integer time = NumericHelper.toInteger(StringUtils.formatTime());
        PublishWorkOut out = new PublishWorkOut();
        Integer endDate = in.getEndDate();
        Integer endTime = in.getEndTime();
        Integer publishDate = in.getPublishDate();
        Integer publishTime = in.getPublishTime();
        if (publishDate == null || publishTime == null || endDate == null || endTime == null) {
            throw new BusinessException(ErrorCode.TEACHER_111);
        }
        Condition workCondition = new Condition(WorkEntity.class);
        workCondition.createCriteria().andEqualTo("workId", in.getWorkId());
        WorkEntity workEntity = new WorkEntity();
        workEntity.setPublishDate(publishDate);
        workEntity.setPublishTime(publishTime);
        workEntity.setEndDate(endDate);
        workEntity.setEndTime(endTime);
        if (date > publishDate || (date.equals(publishDate) && time >= publishTime)){
            workEntity.setIsPublish(1);
        }else {
            workEntity.setIsPublish(0);
        }
        workMapper.updateByConditionSelective(workEntity, workCondition);
        return out;
    }

    @Override
    @Transactional
    public PublishWorkOut editEndWork(PublishWorkIn in) {
        PublishWorkOut out = new PublishWorkOut();
        Condition workCondition = new Condition(WorkEntity.class);
        workCondition.createCriteria().andEqualTo("workId", in.getWorkId());
        WorkEntity workEntity = new WorkEntity();
        workEntity.setIsEnd(in.getIsEnd());
        workMapper.updateByConditionSelective(workEntity, workCondition);
        return out;
    }

    @Override
    @Transactional
    public PublishWorkOut deleteWork(PublishWorkIn in) {
        PublishWorkOut out = new PublishWorkOut();
        //删除工作表
        Condition workCondition = new Condition(WorkEntity.class);
        workCondition.createCriteria().andEqualTo("workId", in.getWorkId());
        workMapper.deleteByCondition(workCondition);
        //删除题目表
        Condition questionCondition = new Condition(QuestionEntity.class);
        questionCondition.createCriteria().andEqualTo("workId", in.getWorkId());
        questionMapper.deleteByCondition(questionCondition);
        return out;
    }

    @Override
    public List<UserEntity> queryUser(QueryUserIn in) {
        Integer userId = in.getUserId();
        UserEntity userEntityQuery = new UserEntity();
        userEntityQuery.setUserId(userId);
        UserEntity userEntity = userMapper.selectOne(userEntityQuery);
        Condition userCondition = new Condition(UserEntity.class);
        userCondition.createCriteria().andEqualTo("grade", in.getGrade())
                .andEqualTo("academyId", in.getAcademyId())
                .andEqualTo("classId", in.getClassId())
                .andEqualTo("schoolId", userEntity.getSchoolId());
        List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);
        if (!CollectionUtils.isEmpty(userEntityList)) {
            //查看是否有已经在课程里面的
            List<Integer> userIdList = userEntityList.stream().map(t -> t.getUserId()).collect(Collectors.toList());
            Condition chooseCondition = new Condition(ChooseEntity.class);
            chooseCondition.createCriteria().andEqualTo("courseId", in.getCourseId())
                    .andIn("userId", userIdList);
            List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
            if (!CollectionUtils.isEmpty(chooseEntityList)) {
                List<Integer> filterUserId = chooseEntityList.stream().map(t -> t.getUserId()).collect(Collectors.toList());
                userEntityList = userEntityList.stream().filter(t -> !filterUserId.contains(t.getUserId())).collect(Collectors.toList());
            }
        }
        return userEntityList;
    }

    @Override
    public AddUserOut addUser(AddUserIn in) {
        List<ChooseEntity> insertList = new ArrayList<>();
        Integer courseId = in.getCourseId();
        List<Integer> list = in.getList();
        for (Integer id : list) {
            ChooseEntity chooseEntity = new ChooseEntity();
            chooseEntity.setUserId(id);
            chooseEntity.setCourseId(courseId);
            chooseEntity.setJoinDate(NumericHelper.toInteger(StringUtils.formatDate()));
            chooseEntity.setJoinTime(NumericHelper.toInteger(StringUtils.formatTime()));
            insertList.add(chooseEntity);
        }
        chooseMapper.insertList(insertList);
        return new AddUserOut();
    }

    @Override
    public List<CourseUserOut> queryCourseUser(CourseUserIn in) {
        Integer courseId = in.getCourseId();
        String userName = in.getUserName();
        CourseUserBean bean = new CourseUserBean();
        bean.setCourseId(courseId);
        bean.setUserName(userName);
        List<CourseUserOut> list = teacherMapper.queryCourseUser(bean);
        for (CourseUserOut courseUserOut : list) {
            School school = cacheManage.getSchoolCache().getObject(StringUtils.toString(courseUserOut.getSchoolId()));
            courseUserOut.setSchoolName(school.getSchoolName());
        }
        return list;
    }

    @Override
    public void deleteCourseUser(CourseUserIn in) {
        Integer courseId = in.getCourseId();
        Integer delUserId = in.getDelUserId();
        Condition chooseCondition = new Condition(ChooseEntity.class);
        chooseCondition.createCriteria().andEqualTo("userId", delUserId)
                .andEqualTo("courseId", courseId);
        chooseMapper.deleteByCondition(chooseCondition);
    }

    @Override
    public SaveJobOut saveReport(SaveJobIn in) {
        SaveJobOut out = new SaveJobOut();
        Integer workId = in.getWorkId();
        WorkEntity workEntity = new WorkEntity();
        workEntity.setWorkName(in.getTitle());
        workEntity.setFileId(in.getFileId());
        if (workId == null) {
            workEntity.setCourseId(in.getCourseId());
            workEntity.setWorkType(in.getWorkType());
            workEntity.setCreateDate(NumericHelper.toInteger(StringUtils.formatDate()));
            workEntity.setCreateTime(NumericHelper.toInteger(StringUtils.formatTime()));
            workMapper.insertSelective(workEntity);
        } else {
            Condition workCondition = new Condition(WorkEntity.class);
            workCondition.createCriteria().andEqualTo("workId", workId);
            workMapper.updateByConditionSelective(workEntity, workCondition);
        }
        return out;
    }

    @Override
    public EditCourseOut editCourse(EditCourseIn in) {
        Condition courseCondition = new Condition(CourseEntity.class);
        courseCondition.createCriteria().andEqualTo("courseId", in.getCourseId());
        CourseEntity courseEntity = new CourseEntity();
        if (in.getCourseType() != null) {
            courseEntity.setCourseType(in.getCourseType());
        }
        if (in.getStatus() != null) {
            courseEntity.setStatus(in.getStatus());
        }
        if (in.getCourseName() != null) {
            courseEntity.setCourseName(in.getCourseName());
        }
        if (in.getIntroduce() != null) {
            courseEntity.setIntroduce(in.getIntroduce());
        }
        if (in.getScaleOne() != null) {
            courseEntity.setScaleOne(in.getScaleOne());
        }
        if (in.getScaleTwo() != null) {
            courseEntity.setScaleTwo(in.getScaleTwo());
        }
        if (in.getScaleThree() != null) {
            courseEntity.setScaleThree(in.getScaleThree());
        }
        courseMapper.updateByConditionSelective(courseEntity, courseCondition);
        return new EditCourseOut();
    }

    @Override
    public List<CourseQueryOut> getOptionalCourse(CourseQueryIn in) {
        List<CourseQueryOut> list = new ArrayList<>();
        Integer userId = in.getUserId();
        Condition courseCondition = new Condition(CourseEntity.class);
        Example.Criteria criteria = courseCondition.createCriteria();
        criteria.andIn("status", Arrays.asList(0, 2));
        criteria.andEqualTo("courseType", 1);
        if (in.getKey() != null) {
            criteria.andEqualTo("courseId", in.getKey());
        }
        courseCondition.setOrderByClause("create_date desc,create_time desc");
        List<CourseEntity> courseEntities = courseMapper.selectByCondition(courseCondition);
        if (!CollectionUtils.isEmpty(courseEntities)) {
            List<Integer> teacherIdList = courseEntities.stream().map(t -> t.getTeacherId()).collect(Collectors.toList());
            //查询用户
            Condition userCondition = new Condition(UserEntity.class);
            userCondition.createCriteria().andIn("userId", teacherIdList);
            List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);
            for (CourseEntity courseEntity : courseEntities) {
                CourseQueryOut out = new CourseQueryOut();
                out.setCourseId(StringUtils.toString(courseEntity.getCourseId()));
                out.setCourseName(courseEntity.getCourseName());
                out.setImgPath(courseEntity.getImgPath());
                List<UserEntity> userEntities = userEntityList.stream().filter(t -> t.getUserId().equals(courseEntity.getTeacherId())).collect(Collectors.toList());
                out.setUserName(userEntities.get(0).getFullName());
                out.setCourseType(StringUtils.toString(courseEntity.getCourseType()));
                out.setStatus(StringUtils.toString(courseEntity.getStatus()));
                out.setCreateDate(StringUtils.toString(courseEntity.getCreateDate()));
                out.setCreateTime(StringUtils.toString(courseEntity.getCreateTime()));
                out.setCredit(StringUtils.toString(courseEntity.getCredit()));
                out.setIntroduce(courseEntity.getIntroduce());
                list.add(out);
            }
        }
        return list;
    }

    @Override
    public QueryWorkDoneOut queryWorkDone(GetJobIn in) {
        QueryWorkDoneOut out = new QueryWorkDoneOut();
        List<UndoInfo> undoInfoList = new ArrayList<>();
        List<DoneInfo> doneInfoList = new ArrayList<>();
        Integer workId = in.getWorkId();
        Integer courseId = in.getCourseId();
        //完成表
        CompleteEntity completeEntityQuery = new CompleteEntity();
        completeEntityQuery.setWorkId(workId);
        completeEntityQuery.setCompleteType(1);
        List<CompleteEntity> completeEntityList = completeMapper.select(completeEntityQuery);
        List<Integer> doneUserIdList = completeEntityList.stream().map(t -> t.getUserId()).collect(Collectors.toList());
        //选择表
        ChooseEntity chooseEntityQuery = new ChooseEntity();
        chooseEntityQuery.setCourseId(courseId);
        List<ChooseEntity> chooseEntityList = chooseMapper.select(chooseEntityQuery);
        List<Integer> userIdList = chooseEntityList.stream().map(t -> t.getUserId()).collect(Collectors.toList());
        //
        Condition userCondition = new Condition(UserEntity.class);
        userCondition.createCriteria().andIn("userId", userIdList);
        List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);

        List<Integer> academyIdList = userEntityList.stream().map(t -> t.getAcademyId()).collect(Collectors.toList());
        Condition academyCondition = new Condition(AcademyEntity.class);
        academyCondition.createCriteria().andIn("academyId", academyIdList)
                .andEqualTo("status", 1);
        //学院
        List<AcademyEntity> academyEntityList = academyMapper.selectByCondition(academyCondition);
        Map<Integer, String> academyMap = academyEntityList.stream().collect(Collectors.toMap(AcademyEntity::getAcademyId, AcademyEntity::getAcademyName));
        List<Integer> classIdList = userEntityList.stream().map(t -> t.getClassId()).collect(Collectors.toList());
        Condition classCondition = new Condition(ClassEntity.class);
        classCondition.createCriteria().andIn("classId", classIdList)
                .andEqualTo("status", 1);
        //专业
        List<ClassEntity> classEntityList = classMapper.selectByCondition(classCondition);
        Map<Integer, String> classMap = classEntityList.stream().collect(Collectors.toMap(ClassEntity::getClassId, ClassEntity::getClassName));
        for (Integer userId : userIdList) {
            List<UserEntity> entityList = userEntityList.stream().filter(t -> t.getUserId().equals(userId)).collect(Collectors.toList());
            Integer academyId = entityList.get(0).getAcademyId();
            Integer classId = entityList.get(0).getClassId();
            Integer schoolId = entityList.get(0).getSchoolId();
            School school = cacheManage.getSchoolCache().getObject(StringUtils.toString(schoolId));
            List<CompleteEntity> completeEntities = completeEntityList.stream().filter(t -> t.getUserId().equals(userId)).collect(Collectors.toList());
            if (doneUserIdList.contains(userId)) {
                DoneInfo doneInfo = new DoneInfo();
                doneInfo.setUserId(StringUtils.toString(userId));
                doneInfo.setUserName(entityList.get(0).getFullName());
                doneInfo.setCompleteDate(StringUtils.toString(completeEntities.get(0).getCompleteDate()));
                doneInfo.setCompleteTime(StringUtils.toString(completeEntities.get(0).getCompleteDate()));
                doneInfo.setAcademyName(academyMap.get(academyId));
                doneInfo.setClassName(classMap.get(classId));
                doneInfo.setSchoolName(school.getSchoolName());
                doneInfo.setIsCorrect(StringUtils.toString(completeEntities.get(0).getIsCorrect()));
                doneInfoList.add(doneInfo);
            } else {
                UndoInfo undoInfo = new UndoInfo();
                undoInfo.setUserId(StringUtils.toString(userId));
                undoInfo.setUserName(entityList.get(0).getFullName());
                undoInfo.setAcademyName(academyMap.get(academyId));
                undoInfo.setClassName(classMap.get(classId));
                undoInfo.setSchoolName(school.getSchoolName());
                undoInfoList.add(undoInfo);
            }
        }
        out.setDoneInfoList(doneInfoList);
        out.setUndoInfoList(undoInfoList);
        return out;
    }

  @Override
  public void saveComment(SaveCommentIn in) {
    Condition completeCondition = new Condition(CompleteEntity.class);
    completeCondition.createCriteria().andEqualTo("workId",in.getWorkId())
      .andEqualTo("userId",in.getUserId());
    CompleteEntity completeEntity = new CompleteEntity();
    completeEntity.setComment(in.getComment());
    completeEntity.setIsCorrect(1);
    completeEntity.setScore(in.getScore());
    completeMapper.updateByConditionSelective(completeEntity,completeCondition);
  }

    @Override
    public void initiateCheckIn(CheckInParam param) {
        Integer courseId = NumericHelper.toInteger(param.getCourseId());
        CheckEntity checkEntity = new CheckEntity();
        checkEntity.setCheckCode(param.getCode());
        checkEntity.setCourseId(courseId);
        checkEntity.setCheckDate(NumericHelper.toInteger(StringUtils.formatDate()));
        checkEntity.setCheckTime(NumericHelper.toInteger(StringUtils.formatTime()));
        checkMapper.insertSelective(checkEntity);
        //提醒学生签到
        serviceClient.sendMailToCheck(courseId,checkEntity.getCheckId());
    }

    @Override
    public QueryCheckOut queryCheck(QueryCheckParam param) {
        QueryCheckOut out = new QueryCheckOut();
        String courseId = param.getCourseId();
        Condition chooseCondition = new Condition(ChooseEntity.class);
        chooseCondition.createCriteria().andEqualTo("courseId",NumericHelper.toInteger(courseId));
        List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
        List<Integer> userIdList = chooseEntityList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(userIdList)){
            Condition userCondition = new Condition(UserEntity.class);
            userCondition.createCriteria().andIn("userId",userIdList);
            List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);
            Map<Integer, List<UserEntity>> userMap = userEntityList.stream().collect(Collectors.groupingBy(t -> t.getUserId()));
            //
            Condition checkCondition = new Condition(CheckEntity.class);
            checkCondition.createCriteria().andEqualTo("courseId",NumericHelper.toInteger(courseId));
            checkCondition.setOrderByClause("check_date desc,check_time desc");
            List<CheckEntity> checkEntities = checkMapper.selectByCondition(checkCondition);
            //
            List<Integer> checkIdList = checkEntities.stream().map(t -> t.getCheckId()).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(checkIdList)){
                Condition checkIdCondition = new Condition(CheckInEntity.class);
                checkIdCondition.createCriteria().andIn("checkId",checkIdList);
                checkIdCondition.setOrderByClause("check_date desc,check_time desc");
                List<CheckInEntity> checkInEntityList = checkInMapper.selectByCondition(checkIdCondition);
                Map<Integer, List<CheckInEntity>> listMap = checkInEntityList.stream().collect(Collectors.groupingBy(t -> t.getCheckId()));
                List<QueryCheckVo> list = new ArrayList<>();
                for (CheckEntity checkEntity : checkEntities) {
                    Integer checkId = checkEntity.getCheckId();
                    List<CheckInEntity> checkInEntities = listMap.get(checkId);
                    if (checkInEntities == null){
                        checkInEntities = new ArrayList<>();
                    }
                    List<Integer> userIds = checkInEntities.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
                    List<Integer> unCheckUserList = userEntityList.stream()
                            .filter(t -> !userIds.contains(t.getUserId())).map(t -> t.getUserId()).distinct().collect(Collectors.toList());
                    QueryCheckVo queryCheckVo = new QueryCheckVo();
                    queryCheckVo.setCheckId(courseId);
                    queryCheckVo.setCheckDate(checkEntity.getCheckDate());
                    queryCheckVo.setCheckTime(checkEntity.getCheckTime());
                    List<CheckVo> checkVoList = new ArrayList<>();
                    for (CheckInEntity checkInEntity : checkInEntities) {
                        CheckVo checkVo = new CheckVo();
                        checkVo.setUserId(checkInEntity.getUserId());
                        checkVo.setUserName(userMap.get(checkInEntity.getUserId()).get(0).getFullName());
                        checkVoList.add(checkVo);
                    }
                    queryCheckVo.setCheckVoList(checkVoList);
                    //
                    List<CheckVo> unCheckVoList = new ArrayList<>();
                    for (Integer userId : unCheckUserList) {
                        CheckVo checkVo = new CheckVo();
                        checkVo.setUserId(userId);
                        checkVo.setUserName(userMap.get(userId).get(0).getFullName());
                        unCheckVoList.add(checkVo);
                    }
                    queryCheckVo.setUnCheckVoList(unCheckVoList);
                    list.add(queryCheckVo);
                }
                out.setList(list);
            }
        }
        return out;
    }

    @Override
    public void exportPuntaje(String courseId, HttpServletResponse response) {
        Integer cId = NumericHelper.toInteger(courseId);
        CourseEntity courseEntityQuery = new CourseEntity();
        courseEntityQuery.setCourseId(cId);
        CourseEntity courseEntity = courseMapper.selectOne(courseEntityQuery);
        Integer scaleOne = courseEntity.getScaleOne();
        Integer scaleTwo = courseEntity.getScaleTwo();
        Integer scaleThree = courseEntity.getScaleThree();
        //课程所有学生
        Condition chooseCondition = new Condition(ChooseEntity.class);
        chooseCondition.createCriteria().andEqualTo("courseId",cId);
        List<ChooseEntity> chooseEntityList = chooseMapper.selectByCondition(chooseCondition);
        List<Integer> userIdList = chooseEntityList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());

        Condition userCondition = new Condition(UserEntity.class);
        userCondition.createCriteria().andIn("userId",userIdList);
        List<UserEntity> userEntityList = userMapper.selectByCondition(userCondition);

        //作业表
        Condition workCondition = new Condition(WorkEntity.class);
        workCondition.createCriteria().andEqualTo("courseId",cId);
        List<WorkEntity> workEntityList = workMapper.selectByCondition(workCondition);

        //作业完成表
        List<Integer> workIdList = workEntityList.stream().map(t -> t.getWorkId()).collect(Collectors.toList());
        Condition completeCondition = new Condition(CompleteEntity.class);
        completeCondition.createCriteria().andIn("workId",workIdList);
        List<CompleteEntity> completeEntityList = completeMapper.selectByCondition(completeCondition);
        Map<String, CompleteEntity> listMap = completeEntityList.stream().collect((Collectors.toMap(
                t->t.getWorkId() +"+"+ t.getUserId(), Function.identity(), (oldVal, newVal) -> newVal)));

        //
        Condition checkCondition = new Condition(CheckEntity.class);
        checkCondition.createCriteria().andEqualTo("courseId",cId);
        List<CheckEntity> checkEntityList = checkMapper.selectByCondition(checkCondition);
        List<Integer> checkIdList = checkEntityList.stream().map(t -> t.getCheckId()).distinct().collect(Collectors.toList());
        List<CheckInEntity> checkInEntities = new ArrayList<>();
        if (!CollectionUtils.isEmpty(checkIdList)){
            Condition checkInCondition = new Condition(CheckInEntity.class);
            checkInCondition.createCriteria().andIn("checkId",checkIdList);
            checkInEntities = checkInMapper.selectByCondition(checkInCondition);
            if (CollectionUtils.isEmpty(checkInEntities)){
                checkInEntities = new ArrayList<>();
            }
        }

        List<CoursePuntajeInfo> list = new ArrayList<>();
        for (UserEntity userEntity : userEntityList) {
            CoursePuntajeInfo info = new CoursePuntajeInfo();
            info.setUserId(userEntity.getUserId());
            info.setUserName(userEntity.getFullName());
            info.setStuId(userEntity.getStuId());
            Double totalOne = 0D;
            Integer countOne = 0;
            Double totalTwo = 0D;
            Integer countTwo = 0;
            Integer totalThree = 0;
            Integer countThree = 0;
            for (WorkEntity workEntity : workEntityList) {
                Integer workType = workEntity.getWorkType();
                CompleteEntity completeEntity = listMap.get(workEntity.getWorkId() + "+" + userEntity.getUserId());
                if (completeEntity == null)
                    continue;
                Double score = completeEntity.getScore();
                if (workType == 0){
                    totalOne += NumericHelper.zeroNull(score);
                    countOne ++;
                }else if (workType == 1){
                    totalTwo += NumericHelper.zeroNull(score);
                    countTwo ++;
                }
            }
            for (CheckEntity checkEntity : checkEntityList) {
                Integer checkId = checkEntity.getCheckId();
                long count = checkInEntities.stream().filter(t -> t.getCheckId().equals(checkId) && t.getUserId().equals(userEntity.getUserId())).count();
                if (count > 0){
                    totalThree ++;
                }
                countThree ++;
            }
            if (countThree == 0){
                info.setGradeOne(new BigDecimal("0"));
            }else {
                info.setGradeOne(NumericHelper.toBigDecimal(totalThree).multiply(NumericHelper.toBigDecimal(scaleOne)).divide(NumericHelper.toBigDecimal(countThree), 2, BigDecimal.ROUND_HALF_UP));
            }
            if (countOne == 0){
                info.setGradeTwo(new BigDecimal("0"));
            }else {
                info.setGradeTwo(NumericHelper.toBigDecimal(totalOne).multiply(NumericHelper.toBigDecimal(scaleTwo)).divide(NumericHelper.toBigDecimal(countOne), 2, BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP));
            }
            if (countTwo == 0){
                info.setGradeThree(new BigDecimal("0"));
            }else {
                info.setGradeThree(NumericHelper.toBigDecimal(totalTwo).multiply(NumericHelper.toBigDecimal(scaleThree)).divide(NumericHelper.toBigDecimal(countTwo), 2, BigDecimal.ROUND_HALF_UP).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP));
            }
            info.setTotalGrade(info.getGradeOne().add(info.getGradeTwo()).add(info.getGradeThree()));
            list.add(info);
        }


        //导出excel

        String[] title = {"学号", "名称", "考勤("+scaleOne+"%)","平时作业("+scaleTwo+"%)","实验报告("+scaleThree+"%)","汇总"};
        //创建excel工作簿
        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建工作表sheet
        XSSFSheet sheet = workbook.createSheet();
        sheet.setColumnWidth(0,3384);
        sheet.setColumnWidth(2,3384);
        sheet.setColumnWidth(3,3384);
        sheet.setColumnWidth(4,3384);
        //创建第一行
        XSSFRow row = sheet.createRow(0);
        XSSFCell cell = null;
        //插入第一行的表头
        for (int i = 0; i < title.length; i++) {
            cell = row.createCell(i);
            cell.setCellValue(title[i]);
        }
        for (int i = 1; i <list.size()+1; i++) {
            XSSFRow nrow = sheet.createRow(i);
            XSSFCell ncell = nrow.createCell(0);
            CoursePuntajeInfo coursePuntajeInfo = list.get(i - 1);
            ncell.setCellValue(coursePuntajeInfo.getStuId());
            ncell=nrow.createCell(1);
            ncell.setCellValue(coursePuntajeInfo.getUserName());
            ncell=nrow.createCell(2);
            ncell.setCellValue(StringUtils.toString(coursePuntajeInfo.getGradeOne()));
            ncell=nrow.createCell(3);
            ncell.setCellValue(StringUtils.toString(coursePuntajeInfo.getGradeTwo()));
            ncell=nrow.createCell(4);
            ncell.setCellValue(StringUtils.toString(coursePuntajeInfo.getGradeThree()));
            ncell=nrow.createCell(5);
            ncell.setCellValue(StringUtils.toString(coursePuntajeInfo.getTotalGrade()));
        }
        //创建excel文件
        //这里的路径就是项目下的resources文件夹里面filePath
        String filePath="testdata.xlsx";
        File file=new File(filePath);
        try {
            file.createNewFile();
            //将excel写入
            FileOutputStream stream= FileUtils.openOutputStream(file);
            workbook.write(stream);
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        File returnZipFile = new File(filePath);
        response.setCharacterEncoding("utf-8");
        response.setHeader("content-type", "application/octet-stream");
        String fileName = courseEntity.getCourseName() + "成绩汇总.xlsx";
        try {
            response.addHeader("Content-Disposition","attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] buffer = new byte[1024*8];
        FileInputStream fis = null;
        OutputStream os = null;
        try {
            fis = new FileInputStream(returnZipFile);
            os = response.getOutputStream();
            int byteLenth = 0;
            while((byteLenth = fis.read(buffer)) != -1){
                os.write(buffer, 0, byteLenth);
            }
        } catch (IOException e) {
            log.error("获取下载文件失败", e);
        }finally {
            try {
                if(os != null){
                    os.close();
                }
                if(fis != null){
                    fis.close();
                }
            } catch (IOException e) {
                log.error("关闭流失败", e);
            }
        }
    }
}
